﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Mimoza.ObjectLayer;
using Mimoza.Apps.Console.ViewModel;

namespace Mimoza.Apps.Console.View
{
    public partial class HostsViewBase : BaseView
    {
        public HostsViewBase()
        {
            InitializeComponent();
        }

        public override void Init(BaseViewModel viewModel)
        {                     
            m_viewModel = viewModel;

            this.Dock = DockStyle.Fill;            
            this.listView.ContextMenuStrip = this.contextMenuStrip;

            m_viewModel.PropertyChanged += new PropertyChangedEventHandler(HostsViewModel_PropertyChanged);
            m_viewModel.OnObjectChanged += new EventHandler<Mimoza.ObjectLayer.ObjectLayer_ObjectChangedEventArgs>(HostsViewModel_OnObjectChanged);

            AddCommand2Context(m_viewModel, this.contextMenuStrip);

            DeleteZeroWidthColumns();

            InitTimer();
        }

        public void Fill()
        {
            listView.Items.Clear();

            foreach (Mimoza.ObjectLayer.Host host in (m_viewModel as Mimoza.Apps.Console.ViewModel.HostsViewModelBase).GetHosts())
            {
                InsertHost(host);
            }
        }

        public virtual void OnItemUpdate(Mimoza.ObjectLayer.Host host, ListViewItem item)
        {
        }

        private void InitTimer()
        {
            timerUpdateStatus.Interval = (int)((Mimoza.Common.GlobalSettings.c_DefaultPingTimeout / 3.0) * 1000);
            timerUpdateStatus.Enabled = true;
        }

        private void InsertHost(Mimoza.ObjectLayer.Host host)
        {
            Mimoza.ObjectLayer.Container currentContainer = (m_viewModel as Mimoza.Apps.Console.ViewModel.HostsViewModelBase).CurrentContainer;
            if (currentContainer != null && host.Parent.ID != currentContainer.ID)
            {
                return;
            }

            ListViewItem item = new ListViewItem();

            FillListItem(host, item);

            listView.Items.Add(item);
        }


        private void UpdateHost(Mimoza.ObjectLayer.Host host)
        {
            if (host.Parent.ID != (m_viewModel as Mimoza.Apps.Console.ViewModel.HostsViewModelBase).CurrentContainer.ID)
            {
                return;
            }

            foreach (ListViewItem item in listView.Items)
            {
                if ((item.Tag as Host).ID == host.ID)
                {
                    FillListItem(host, item);
                    break;
                }
            }
        }

        private void FillListItem(Mimoza.ObjectLayer.Host host, ListViewItem item)
        {
            item.ImageIndex = GetHostImageIndex(host);

            item.Tag = host;
            item.Text = host.Name;

            if (item.SubItems.Count < listView.Columns.Count)
            {
                foreach (var column in listView.Columns)
                {
                    item.SubItems.Add(new ListViewItem.ListViewSubItem());
                }
            }

            SetItemValue(item, "columnIP", host.IPAddress);
            SetItemValue(item, "columnMAC", host.MACAddress);
            SetItemValue(item, "columnOS", host.OS);
            SetItemValue(item, "columnModel", host.Model);
            SetItemValue(item, "columnVersion", host.Version);
            SetItemValue(item, "columnLastUpdateTime", host.LastConnectionDate.ToString("g"));
            if (GetColumnIndex("columnContainerName") >= 0)
            {
                SetItemValue(item, "columnContainerName", host.Parent.Name);
            }

            OnItemUpdate(host, item);
        }

        private void SetItemValue(ListViewItem item, string columnName, string value)
        {
            int columnIdx = GetColumnIndex(columnName);
            if (columnIdx >= 0) item.SubItems[columnIdx].Text = value;
        }

        private int GetColumnIndex(string columnName)
        {
            IEnumerable<ColumnHeader> columns = listView.Columns.Cast<ColumnHeader>();
            var columnIdx = (from col in columns
                             where (string)(col.Tag) == columnName
                             select col.Index).FirstOrDefault();
            if (columnIdx == 0) columnIdx = (-1); 
            return columnIdx;
        }

        private void DeleteHost(Mimoza.ObjectLayer.Host host)
        {
            if (host.Parent.ID != (m_viewModel as Mimoza.Apps.Console.ViewModel.HostsViewModelBase).CurrentContainer.ID)
            {
                return;
            }

            foreach (ListViewItem item in listView.Items)
            {
                if ((item.Tag as Host).ID == host.ID)
                {
                    listView.Items.Remove(item);
                    break;
                }
            }
        }

        private void HostsViewModel_OnObjectChanged(object sender, Mimoza.ObjectLayer.ObjectLayer_ObjectChangedEventArgs e)
        {
            Mimoza.ObjectLayer.Host host = e.Object as Mimoza.ObjectLayer.Host;

            switch (e.EventType)
            {
                case ObjectLayerEventType.ObjectInserted:
                    Action<Mimoza.ObjectLayer.Host> action = InsertHost;
                    Invoke(action, host);
                    break;
                case ObjectLayerEventType.ObjectUpdated:
                    Action<Mimoza.ObjectLayer.Host> actionUpdate = UpdateHost;
                    Invoke(actionUpdate, host); 
                    break;
                case ObjectLayerEventType.ObjectDeleted:
                    Action<Mimoza.ObjectLayer.Host> actionDelete = DeleteHost;
                    Invoke(actionDelete, host); 
                    break;
            }
        }
        private void HostsViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "CurrentContainer")
            {
                Fill();
            }
        }

        private void listView_Leave(object sender, EventArgs e)
        {
            m_viewModel.InFocus = false;
        }

        private void listView_Enter(object sender, EventArgs e)
        {
            m_viewModel.InFocus = true;
        }

        private void listView_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (listView.SelectedItems.Count != 0)
            {
                object []objs = new object[listView.SelectedItems.Count];
                for (int i = 0; i < listView.SelectedItems.Count; i++)
                {
                     objs[i]= listView.SelectedItems[i].Tag;
                }
                m_viewModel.Context = objs;
            }
        }

        private void DeleteZeroWidthColumns()
        {
            List<int> columnsIndexes = new List<int>();
            foreach (ColumnHeader columnHeader in listView.Columns)
            {
                if (columnHeader.Width == 0) columnsIndexes.Insert(0, columnHeader.Index);
            }

            foreach (var columnIndex in columnsIndexes)
            {
                listView.Columns.RemoveAt(columnIndex);
            }
        }

        private void timerUpdateStatus_Tick(object sender, EventArgs e)
        {
            foreach (ListViewItem item in listView.Items)
            {
                if (item.Tag == null) continue;

                int curImageIndex = GetHostImageIndex(item.Tag as Host);
                if (item.ImageIndex != curImageIndex) item.ImageIndex = curImageIndex;
            }
        }

        private int GetHostImageIndex(Host host)
        {
            return host.IsActive ? 0 : 1; // 0 - Normal, 1 - Disable, 2 - Hot
        }
    }
}
